אסטרטגיות להעברת האתר מהסתמכות על מחרוזת הסוכן המשתמש לשימוש ברמזים החדשים על הלקוח (Client Hints) לגבי הסוכן המשתמש.
תאריך פרסום: 19 במאי 2021
המחרוזת של סוכן המשתמש היא שטח משמעותי ליצירת טביעות אצבע פסיביות בדפדפנים, וגם קשה לעבד אותה. עם זאת, יש כל מיני סיבות לגיטימיות לאיסוף ולעיבוד של נתוני סוכן משתמש, ולכן מה שדרוש הוא דרך לפתרון טוב יותר. רמזים ללקוח של סוכן משתמש מספקים דרך מפורשת להצהיר על הצורך בנתוני סוכן משתמש, וגם שיטות להחזרת הנתונים בפורמט קל לשימוש.
כאן נסביר איך מבצעים ביקורת על הגישה לנתוני סוכן המשתמש ומעבירים את השימוש במחרוזת של סוכן המשתמש לרמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש.
ביקורת על איסוף נתוני סוכן משתמש ועל השימוש בהם
כמו בכל סוג של איסוף נתונים, תמיד חשוב להבין למה אתם אוספים אותם. השלב הראשון, לא משנה אם תבצעו פעולה כלשהי או לא, הוא להבין איפה אתם משתמשים בנתוני סוכן המשתמש ולמה.
אם אתם לא יודעים אם נעשה שימוש בנתוני סוכן המשתמש או איפה, כדאי לחפש בקוד הקצה הקדמי שימוש ב-navigator.userAgent
ובקוד הקצה העורפי שימוש בכותרת ה-HTTP User-Agent
. כדאי גם לבדוק את הקוד של הקצה הקדמי כדי לראות אם יש בו שימוש בתכונות שכבר הוצאו משימוש, כמו navigator.platform
ו-navigator.appVersion
.
מבחינה פונקציונלית, כדאי לחשוב על כל מקום בקוד שבו אתם מתעדים או מעבדים:
- השם או הגרסה של הדפדפן
- השם או הגרסה של מערכת ההפעלה
- היצרן או הדגם של המכשיר
- סוג המעבד, הארכיטקטורה או רמת הביטים (לדוגמה, 64 ביט)
סביר להניח שאתם משתמשים גם בספרייה או בשירות של צד שלישי כדי לעבד את סוכן המשתמש. במקרה כזה, כדאי לבדוק אם הם מתעדכנים כדי לתמוך ברמזים על הלקוח (Client Hints) לגבי סוכן המשתמש.
האם אתם משתמשים רק בנתונים בסיסיים של סוכן משתמש?
קבוצת ברירת המחדל של רמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש כוללת:
Sec-CH-UA
: שם הדפדפן והגרסה הראשית או המשמעותיתSec-CH-UA-Mobile
: ערך בוליאני שמציין מכשיר ניידSec-CH-UA-Platform
: שם מערכת ההפעלה
גם בגרסה המקוצרת של מחרוזת סוכן המשתמש שתוצג, המידע הבסיסי הזה יישמר באופן תואם לאחור. לדוגמה, במקום Chrome/90.0.4430.85
, המחרוזת תכלול את Chrome/90.0.0.0
.
אם אתם בודקים רק את מחרוזת סוכן המשתמש כדי לזהות את שם הדפדפן, את הגרסה הראשית או את מערכת ההפעלה, הקוד ימשיך לפעול, אבל סביר להניח שתראו אזהרות על הוצאה משימוש.
אפשר ורצוי לעבור לרמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש, אבל יכול להיות שיש לכם קודים מדור קודם או מגבלות משאבים שמונעים זאת. הפחתת המידע במחרוזת של סוכן המשתמש באופן תואם לאחור נועדה להבטיח שלמרות שהקוד הקיים יקבל מידע פחות מפורט, הוא עדיין ישמור על הפונקציונליות הבסיסית.
שיטות
יש כמה אסטרטגיות שאפשר להשתמש בהן כדי להעביר את השימוש במחרוזת של סוכן המשתמש לרמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש.
JavaScript API בצד הלקוח על פי דרישה
אם אתם משתמשים ב-navigator.userAgent
, כדאי לעבור להעדפת navigator.userAgentData
לפני שתחזרו לנתח את מחרוזת סוכן המשתמש.
if (navigator.userAgentData) {
// use new hints
} else {
// fall back to user-agent string parsing
}
אם בודקים אם המשתמש נמצא בנייד או במחשב, משתמשים בערך הבוליאני mobile
:
const isMobile = navigator.userAgentData.mobile;
userAgentData.brands
הוא מערך של אובייקטים עם המאפיינים brand
ו-version
, שבהם הדפדפן יכול לרשום את התאימות שלו למותגים האלה. אפשר לגשת אליו ישירות כמערך, או להשתמש בקריאה some()
כדי לבדוק אם יש רשומה ספציפית:
function isCompatible(item) {
// In real life you most likely have more complex rules here
return ['Chromium', 'Google Chrome', 'NewBrowser'].includes(item.brand);
}
if (navigator.userAgentData.brands.some(isCompatible)) {
// browser reports as compatible
}
אם אתם זקוקים לאחד מהערכים המפורטים יותר של סוכן המשתמש עם אנטרופי גבוה, עליכם לציין אותו ולבדוק את התוצאה ב-Promise
המוחזר:
navigator.userAgentData.getHighEntropyValues(['model'])
.then(ua => {
// requested hints available as attributes
const model = ua.model
});
כדאי להשתמש באסטרטגיה הזו גם אם רוצים לעבור עיבוד בצד השרת לעיבוד בצד הלקוח. ל-JavaScript API לא נדרשת גישה לכותרות של בקשות HTTP, כך שאפשר לבקש ערכים של סוכן משתמש בכל שלב.
כותרת סטטית בצד השרת
אם אתם משתמשים בכותרת הבקשה User-Agent
בשרת והצרכים שלכם לגבי הנתונים האלה עקביים יחסית בכל האתר, תוכלו לציין את הטיפים ללקוח כקבוצה סטטית בתשובות שלכם. זוהי גישה פשוטה יחסית, כי בדרך כלל צריך להגדיר אותה רק במיקום אחד. לדוגמה, יכול להיות שהיא תופיע בהגדרות של שרת האינטרנט אם כבר הוספתם כותרות, בהגדרות האירוח או בהגדרות ברמה העליונה של המסגרת או הפלטפורמה שבהם אתם משתמשים באתר.
כדאי להשתמש באסטרטגיה הזו אם אתם מבצעים טרנספורמציה או התאמה אישית של התשובות שמוצגות על סמך נתוני סוכן המשתמש.
דפדפנים או לקוחות אחרים עשויים לספק רמזים שונים כברירת מחדל, לכן מומלץ לציין את כל מה שדרוש לכם, גם אם הוא בדרך כלל מסופק כברירת מחדל.
לדוגמה, הגדרות ברירת המחדל הנוכחיות של Chrome יוצגו כך:
⬇️ כותרות התגובה
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
אם רוצים לקבל גם את דגם המכשיר בתשובות, צריך לשלוח:
⬇️ כותרות התגובה
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA
כשמעובדים את הבקשה בצד השרת, צריך קודם לבדוק אם הכותרת Sec-CH-UA
הרצויה נשלחה, ואז לעבור לניתוח הכותרת User-Agent
אם היא לא זמינה.
הענקת הרשאות לטיפים לבקשות מ-origin שונים
אם אתם מבקשים משאבים משניים ממקורות שונים או מאתרים שונים, שדורשים שליחת רמזים על הלקוח (Client Hints) לגבי סוכן המשתמש בבקשות שלהם, תצטרכו לציין את הרמזים הרצויים באופן מפורש באמצעות מדיניות הרשאות.
לדוגמה, נניח ש-https://blog.site
מארח משאבים ב-https://cdn.site
שיכולים להחזיר משאבים שעברו אופטימיזציה למכשיר ספציפי.
https://blog.site
יכול לבקש את ההצעה Sec-CH-UA-Model
, אבל צריך להעביר אותה באופן מפורש ל-https://cdn.site
באמצעות הכותרת Permissions-Policy
. רשימת הרמזים שנשלטים על ידי מדיניות זמינה בטיוטה של התשתית לרמזים על הלקוח (Client Hints)
⬇️ התשובה מ-blog.site
שמעבירה את ההצעה
Accept-CH: Sec-CH-UA-Model
Permissions-Policy: ch-ua-model=(self "https://cdn.site")
⬆️ בקשה למשאבי משנה ב-cdn.site
כוללת את ההנחיה שהועברה
Sec-CH-UA-Model: "Pixel 5"
אפשר לציין כמה רמזים למקורות מרובים, ולא רק מטווח ch-ua
:
⬇️ תגובה מ-blog.site
שמעבירה כמה רמזים לכמה מקורות
Accept-CH: Sec-CH-UA-Model, DPR
Permissions-Policy: ch-ua-model=(self "https://cdn.site"),
ch-dpr=(self "https://cdn.site" "https://img.site")
הענקת הרשאות ל-iframes
iframes ממקורות שונים פועלים באופן דומה למשאבים ממקורות שונים, אבל אתם צריכים לציין את הטיפים שרוצים להעניק בסמכות ב-allow
.
⬇️ התשובה של blog.site
Accept-CH: Sec-CH-UA-Model
↪️ HTML עבור blog.site
<iframe src="https://widget.site" allow="ch-ua-model"></iframe>
⬆️ בקשה אל widget.site
Sec-CH-UA-Model: "Pixel 5"
המאפיין allow
ב-iframe יגבור על כל כותרת Accept-CH
ש-widget.site
עשויה לשלוח בעצמה, לכן חשוב לוודא שציינתם את כל מה שנחוץ לאתר שמוטמע ב-iframe.
רמזים דינמיים בצד השרת
אם יש חלקים ספציפיים בתהליך השימוש שבהם אתם צריכים מבחר גדול יותר של טיפים מאשר בשאר האתר, תוכלו לבקש את הטיפים האלה על פי דרישה במקום להציג אותם באופן סטטי בכל האתר. ניהול האפשרות הזו מורכב יותר, אבל אם כבר הגדרתם כותרות שונות לכל מסלול, יכול להיות שזה אפשרי.
חשוב לזכור שכל מופע של הכותרת Accept-CH
יחליף למעשה את הקבוצה הקיימת. לכן, אם מגדירים את הכותרת באופן דינמי, כל דף צריך לבקש את הקבוצה המלאה של ההנחיות הנדרשות.
לדוגמה, יכול להיות שיש לכם קטע אחד באתר שבו אתם רוצים להציג סמלים ואמצעי בקרה שתואמים למערכת ההפעלה של המשתמש. לשם כך, מומלץ גם לשלוח משיכה של Sec-CH-UA-Platform-Version
כדי להציג משאבי משנה מתאימים.
⬇️ כותרות התגובה של /blog
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
⬇️ כותרות התגובה של /app
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA
טיפול בהנחיות בצד השרת הנדרשות בבקשה הראשונה
יכול להיות שבמקרים מסוימים תצטרכו יותר מקבוצת ההנחיות שמוגדרת כברירת מחדל בבקשה הראשונה, אבל סביר להניח שזה יקרה לעיתים רחוקות. לכן, חשוב לבדוק את הסיבה לכך.
הבקשה הראשונה היא למעשה הבקשה הראשונה ברמת העליונה של המקור שנשלחה בסשן הגלישה הזה. קבוצת ההנחיות שמוגדרת כברירת מחדל כוללת את שם הדפדפן עם הגרסה הראשית, הפלטפורמה וסממן הניידות. לכן, השאלה היא: האם אתם זקוקים לנתונים מורחבים בטעינת הדף הראשונית?
יש שתי אפשרויות לקבלת רמזים נוספים לגבי הבקשה הראשונה. קודם כול, אפשר להשתמש בכותרת Critical-CH
. הפורמט של ההודעה הזו זהה לפורמט של Accept-CH
, אבל היא מורה לדפדפן לנסות שוב את הבקשה באופן מיידי אם הבקשה הראשונה נשלחה בלי ההנחיה הקריטית.
⬆️ הבקשה הראשונית
[With default headers]
⬇️ כותרות התגובה
Accept-CH: Sec-CH-UA-Model
Critical-CH: Sec-CH-UA-Model
🔃 הדפדפן מנסה שוב את הבקשה הראשונית עם הכותרת הנוספת
[With default headers + …]
Sec-CH-UA-Model: Pixel 5
הבעיה היחידה היא העלות של הניסיון החוזר בבקשה הראשונה, אבל עלות ההטמעה נמוכה יחסית. שולחים את הכותרת הנוספת והדפדפן יטפל בשאר.
במצבים שבהם אתם באמת זקוקים לאיתותים נוספים בעומס הדף הראשון, הצעה לשיפור האמינות של הלקוח מציגה דרך לציין את האותות בהגדרות ברמת החיבור. לשם כך, נעשה שימוש בתוסף Application-Layer Protocol Settings(ALPS) ל-TLS 1.3 כדי לאפשר העברה מוקדמת של הטיפים בחיבורי HTTP/2 ו-HTTP/3. התהליך עדיין נמצא בשלב מוקדם מאוד, אבל אם אתם מנהלים באופן פעיל את הגדרות ה-TLS והחיבור שלכם, זה הזמן האידיאלי לתרום.
תמיכה מדור קודם
יכול להיות שבאתר שלכם יש קוד מדור קודם או קוד של צד שלישי שמסתמך על navigator.userAgent
, כולל חלקים ממחרושת סוכן המשתמש שיופחתו. מומלץ לעבור לשיחות navigator.userAgentData
המקבילות, אבל יש פתרון ביניים.
UA-CH retrofill היא ספרייה קטנה שמאפשרת להחליף את navigator.userAgent
במחרוזת חדשה שנוצרת מהערכים המבוקשים של navigator.userAgentData
.
לדוגמה, הקוד הזה יוצר מחרוזת של סוכן משתמש שכוללת גם את ההצעה 'model':
import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
.then(() => { console.log(navigator.userAgent); });
המחרוזת שמתקבלת תציג את המודל Pixel 5
, אבל עדיין תציג את 92.0.0.0
המופחת כי לא התבקשה ההצעה uaFullVersion
:
Mozilla/5.0 (Linux; Android 10.0; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.0.0 Mobile Safari/537.36
תמיכה נוספת
אם השיטות האלה לא מתאימות לתרחיש לדוגמה שלכם, תוכלו להתחיל דיון ב-repo של privacy-sandbox-dev-support ונוכל לבדוק את הבעיה ביחד.